package Window; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Map.Entry; import java.util.zip.ZipFile; import javax.media.opengl.GL2; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import BrickControlGuide.BrickMovementGuideRenderer; import Builder.AutoSaveManager; import Builder.BuilderConfigurationManager; import Builder.BrickSelectionManager; import Builder.DragSelectionInfoRenderer; import Builder.MainCamera; import Builder.MetaInfoRenderer; import Command.LDrawPart; import Command.PartTypeT; import Common.Box3; import Common.Matrix4; import Common.Ray3; import Common.Size2; import Common.Vector3f; import Connectivity.Direction6T; import Connectivity.GlobalConnectivityManager; import Connectivity.GlobalConnectivityRenderer; import Exports.UpdateManager; import Grouping.GroupingManager; import LDD.bricks.Part; import LDraw.Files.LDrawContainer; import LDraw.Files.LDrawFile; import LDraw.Files.LDrawMPDModel; import LDraw.Files.LDrawModel; import LDraw.Files.LDrawStep; import LDraw.Support.LDrawDirective; import LDraw.Support.LDrawGLCameraScroller; import LDraw.Support.LDrawGLRenderer; import LDraw.Support.LDrawUtilities; import LDraw.Support.MatrixMath; import LDraw.Support.type.LDrawGridTypeT; import LddToLdr.Ldd2Ldr; import Notification.ConnectivityModified; import Notification.ILDrawSubscriber; import Notification.INotificationMessage; import Notification.LDrawDirectiveAdded; import Notification.LDrawDirectiveModified; import Notification.LDrawDirectiveRemoved; import Notification.NotificationCenter; import Notification.NotificationMessageT; import Resource.SoundEffectManager; import UndoRedo.DirectiveAction; import UndoRedo.LDrawUndoRedoManager; import UndoRedo.MovePartsAction; public class MOCBuilder { public final static String APP_NAME = "MOC Builder"; private LDrawGLRenderer glRenderer; private MetaInfoRenderer metaInfoRenderer; private BrickMovementGuideRenderer brickMovementGuideRenderer; private GlobalConnectivityRenderer connectivityRenderer; private DragSelectionInfoRenderer brickSelectionInfoRenderer; private GlobalConnectivityManager globalConnectivityManager; private MainCamera camera; private LDrawStep currentStep = null; private boolean isChanged; private LDrawUndoRedoManager undoRedoManager; private LDrawFile ldrawFile; private BuilderConfigurationManager configurationManager = null; private BrickSelectionManager brickSelectionManager = null; private static MOCBuilder mocBuilder; private Shell shell; public static synchronized MOCBuilder getInstance() { if (mocBuilder == null) { mocBuilder = new MOCBuilder(); } return mocBuilder; } public void setShell(Shell shell) { this.shell = shell; } public static void main(String[] args) { Display.setAppName(APP_NAME); Display display = Display.getDefault(); mocBuilder = new MOCBuilder(); MOCBuilderUI brickBuilderUI = new MOCBuilderUI(mocBuilder); brickBuilderUI.open(display); } long average = 0; private MOCBuilder() { UpdateManager.getInstance(); undoRedoManager = LDrawUndoRedoManager.getInstance(); configurationManager = BuilderConfigurationManager.getInstance(); brickSelectionManager = BrickSelectionManager.getInstance(); globalConnectivityManager = GlobalConnectivityManager.getInstance(); SoundEffectManager.getInstance(); // UpdateManager.getInstance(); newLDrawFile(); initRenderer(); camera.setDistanceBetweenObjectToCamera(400); AutoSaveManager.getInstance(); // ILDrawSubscriber subscriber = new ILDrawSubscriber() { // // @Override // public void receiveNotification(NotificationMessageT messageType, // INotificationMessage msg) { // String partName = ((ConnectivityModified) msg).getPart() // .displayName(); // for (LDrawPart part : getAllPartInFile()) { // if (part.displayName().equals(partName)) { // part.getConnectivityList(true, false); // part.getCollisionBoxList(false); // } // } // } // }; // // NotificationCenter.getInstance().addSubscriber(subscriber, // NotificationMessageT.ConnectivityModified); } public void changeStepIndex(LDrawStep step, int newIndex) { LDrawModel model = ldrawFile.activeModel(); model.removeDirective(step); model.insertDirective(step, newIndex); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawStepAdded); } public void insertDirectiveToWorkingFile(int index, LDrawContainer step, LDrawDirective directive) { insertDirectiveToWorkingFile(index, step, directive, true); } public void addDirectiveToWorkingFile(LDrawDirective directive) { addDirectiveToWorkingFile(directive, true); } public void addDirectiveToWorkingFile(LDrawDirective directive, boolean updateConnectivityManager) { if (LDrawStep.class.isInstance(directive)) { LDrawStep step = (LDrawStep) directive; ldrawFile.activeModel().addStep(step); if (updateConnectivityManager) { for (LDrawDirective tempDirective : step.subdirectives()) { if (tempDirective instanceof LDrawPart == false) continue; LDrawPart part = (LDrawPart) tempDirective; globalConnectivityManager.addPart(part, updateConnectivityManager); brickSelectionManager.addPart(part, updateConnectivityManager); } } } else { if (currentStep == null) currentStep = ldrawFile.activeModel().visibleStep(); addDirectiveToWorkingFile(currentStep, directive, updateConnectivityManager); } } public void addDirectiveToWorkingFile(LDrawStep step, LDrawDirective directive) { addDirectiveToWorkingFile(step, directive, true); } public void insertDirectiveToWorkingFile(int index, LDrawContainer container, LDrawDirective directive, boolean updateConnectivityManager) { if (container == null || container.subdirectives().contains(directive)) { return; } container.insertDirective(directive, index); if (LDrawPart.class.isInstance(directive)) { LDrawPart part = (LDrawPart) directive; globalConnectivityManager.addPart(part, updateConnectivityManager); brickSelectionManager.addPart(part, updateConnectivityManager); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(directive.enclosingDirective(), directive)); updateGridRange(); } else if (directive instanceof LDrawStep) { NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawStepAdded, new LDrawDirectiveAdded(directive.enclosingDirective(), directive)); } else NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawDirectiveAdded, new LDrawDirectiveAdded(directive.enclosingDirective(), directive)); } public void addDirectiveToWorkingFile(LDrawContainer container, LDrawDirective directive, boolean updateConnectivityManager) { if (container == null || container.subdirectives().contains(directive)) { return; } container.addDirective(directive); if (LDrawPart.class.isInstance(directive)) { LDrawPart part = (LDrawPart) directive; globalConnectivityManager.addPart(part, updateConnectivityManager); brickSelectionManager.addPart(part, updateConnectivityManager); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(directive.enclosingDirective(), directive)); updateGridRange(); } else if (directive instanceof LDrawStep) { NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawStepAdded, new LDrawDirectiveAdded(directive.enclosingDirective(), directive)); } else NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawDirectiveAdded, new LDrawDirectiveAdded(directive.enclosingDirective(), directive)); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void addDirectiveToWorkingFileForDragAndDrop(LDrawDirective directive) { if (currentStep == null) currentStep = ldrawFile.activeModel().visibleStep(); currentStep.addDirective(directive); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public LDrawStep addStepToWorkingFile() { LDrawStep step = ldrawFile.activeModel().addStep(); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawStepAdded, new LDrawDirectiveAdded(step.enclosingDirective(), step)); setCurrentStep(step); return step; } public void insertStepToWorkingFileAt(int index, LDrawStep step) { ldrawFile.activeModel().insertDirective(step, index); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawStepAdded, new LDrawDirectiveAdded(step.enclosingDirective(), step)); } public LDrawStep addStepToWorkingFileAt(int index) { LDrawStep step = ldrawFile.activeModel().addStep(index); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawStepAdded, new LDrawDirectiveAdded(step.enclosingDirective(), step)); return step; } public BrickMovementGuideRenderer getBrickMovementGuideRenderer() { return brickMovementGuideRenderer; } public DragSelectionInfoRenderer getBrickSelectionInfoRenderer() { return brickSelectionInfoRenderer; } public MainCamera getCamera() { return camera; } public GlobalConnectivityRenderer getConnectivityRenderer() { return this.connectivityRenderer; } public LDrawStep getCurrentStep() { if (currentStep == null) { return ldrawFile.activeModel().visibleStep(); } else { return currentStep; } } public LDrawGLRenderer getGLRenderer() { return glRenderer; } private Ray3 prevRay = null; private Vector3f prevHitPos; private LDrawPart prevHitPart; private boolean prevIgnoreSelected; private float lastHittedDistance; public LDrawPart getHittedPart(float screenX, float screenY, boolean ignoreSelectedParts) { updateHittedInfoCache(screenX, screenY, ignoreSelectedParts); return prevHitPart; } public Vector3f getHittedPos(float screenX, float screenY, boolean ignoreSelectedParts) { updateHittedInfoCache(screenX, screenY, ignoreSelectedParts); return prevHitPos; } public float getLastHittedDistance() { return lastHittedDistance; } private void updateHittedInfoCache(float screenX, float screenY, boolean ignoreSelectedParts) { Ray3 ray = camera.getRay(screenX, screenY); if (ray.equals(prevRay) && prevIgnoreSelected == ignoreSelectedParts) { return; } Matrix4 transform = new Matrix4(); transform.setIdentity(); HashMap<LDrawDirective, Float> hits = new HashMap<LDrawDirective, Float>(); ldrawFile.hitTest(ray, transform, null, hits); float dist = 200000.0f; Vector3f hitPos = null; LDrawPart hittedPart = null; for (Entry<LDrawDirective, Float> entry : hits.entrySet()) { LDrawPart part = (LDrawPart) entry.getKey(); Float distance = entry.getValue(); if (ignoreSelectedParts == true && part.isDraggingPart()) continue; if (dist > distance.floatValue()) { dist = distance.floatValue(); hitPos = ray.getOrigin() .add(ray.getDirection().scale(distance)); hittedPart = part; } // System.out.println("part " + part.displayName() + " distance" // + distance + // "Position: "+ray.getOrigin().add(ray.getDirection().scale(distance))); } if (hitPos == null) hitPos = camera.screenToWorldXZ(screenX, screenY, 0); prevHitPos = hitPos; prevRay = ray; prevHitPart = hittedPart; prevIgnoreSelected = ignoreSelectedParts; lastHittedDistance = dist; } public MetaInfoRenderer getMetaInfoRenderer() { return metaInfoRenderer; } public LDrawFile getWorkingLDrawFile() { return ldrawFile; } public void initGLReleatedComponent(Size2 size, GL2 gl2) { glRenderer.initWithBoundsCamera(size, camera); LDrawGLCameraScroller scroller = new LDrawGLCameraScroller(); scroller.setDocumentSize(new Size2(800f, 600f)); glRenderer.setDelegate(null, scroller); glRenderer.setLDrawDirective(ldrawFile); glRenderer.prepareOpenGL(gl2); } private void initRenderer() { camera = new MainCamera(); camera.setCurrentCameraRotation(new Vector3f((float) Math.PI, -0.52f, 0)); glRenderer = new LDrawGLRenderer(); metaInfoRenderer = new MetaInfoRenderer(this, camera); brickMovementGuideRenderer = BrickMovementGuideRenderer .getInstance(camera); connectivityRenderer = new GlobalConnectivityRenderer(camera); brickSelectionInfoRenderer = new DragSelectionInfoRenderer(); } public void isVisibleStudHoleMatrix(boolean flag) { connectivityRenderer.isVisible(flag); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } private void ldrawFileChanged() { if (glRenderer == null || glRenderer.isReadyToUse() == false) return; if (glRenderer != null) glRenderer.setLDrawDirective(ldrawFile); camera.setDefault(); currentStep = null; globalConnectivityManager.clear(false); brickSelectionManager.clearAllPart(false); undoRedoManager.clear(); GroupingManager.getInstance().clear(); for (LDrawDirective directive : ldrawFile.activeModel().subdirectives()) { if (LDrawStep.class.isInstance(directive)) { LDrawStep step = (LDrawStep) directive; for (LDrawDirective subDirective : step.subdirectives()) if (LDrawPart.class.isInstance(subDirective)) { LDrawPart part = (LDrawPart) subDirective; globalConnectivityManager.addPart(part, false); globalConnectivityManager.updateMatrix(part); brickSelectionManager.addPart(part, false); } } } brickMovementGuideRenderer.setLDrawPart(null); // globalConnectivityManager.updateMatrixAll(); brickSelectionManager.updateScreenProjectionVerticesMapAll(); updateGridRange(); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); shell.getDisplay().asyncExec(new Runnable() { @Override public void run() { if (ldrawFile != null) { if (ldrawFile.path() != null) shell.setText(APP_NAME + ": " + ldrawFile.path()); else shell.setText(APP_NAME + ": untitled"); } } }); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public boolean moveDirectiveBy(LDrawDirective directive, Vector3f pos) { return moveDirectiveBy(directive, pos, true); } public boolean moveDirectiveBy(LDrawDirective directive, Vector3f pos, boolean useSnap) { boolean isMoved = false; if (LDrawPart.class.isInstance(directive)) { LDrawPart part = (LDrawPart) directive; if (pos != null) isMoved = part.moveBy(new Vector3f(pos.x, pos.y, pos.z), configurationManager.getGridUnit(), useSnap); updateGridRange(); } NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); return isMoved; } public void moveDirectiveTo(LDrawDirective directive, Vector3f pos) { moveDirectiveTo(directive, pos, true); } public void moveDirectiveTo(LDrawDirective directive, Vector3f pos, boolean useSnap) { if (LDrawPart.class.isInstance(directive)) { LDrawPart part = (LDrawPart) directive; if (pos != null) { Matrix4 newTransform = null; long t = System.nanoTime(); newTransform = GlobalConnectivityManager.getInstance() .getClosestConnectablePos(part, pos); long diff = (System.nanoTime() - t); average = (long) (average * 0.8 + diff * 0.2); // System.out.println("avr: " + average + ", " + diff); if (newTransform == null) { newTransform = new Matrix4( brickSelectionManager .getStartMoveTransformMatrix(part)); if (useSnap) pos = LDrawGridTypeT.getSnappedPos(pos, configurationManager.getGridUnit()); newTransform.element[3][0] = pos.x; newTransform.element[3][1] = pos.y; newTransform.element[3][2] = pos.z; } part.setTransformationMatrix(newTransform); } updateGridRange(); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } } public void moveDirectiveToWithoutConnectivity(LDrawDirective directive, Vector3f pos) { boolean useConnectivity = configurationManager.isUseConnectivity(); configurationManager.setUseConnectivity(false); moveDirectiveTo(directive, pos, false); configurationManager.setUseConnectivity(useConnectivity); } public void newLDrawFile() { Display display = Display.getDefault(); Shell shell = display.getActiveShell(); if (shell == null || checkChanged(shell)) { ldrawFile = LDrawFile.newEditableFile(); ldrawFile.activeModel().addStep(); ldrawFile.setPath(null); ldrawFileChanged(); } } public void openFile(final String path) { BackgroundThreadManager.getInstance().add(new Runnable() { @Override public void run() { long t = System.nanoTime(); if (path.toLowerCase().endsWith(".lxfml") || path.toLowerCase().endsWith(".lxf")) { try { Ldd2Ldr ldd2ldr = new Ldd2Ldr( BuilderConfigurationManager .getDefaultDataDirectoryPath() + "Data/ldraw.xml"); String outputFile = BuilderConfigurationManager .getDefaultDataDirectoryPath() + "convertedLdr.ldr"; if (new File(outputFile).exists()) new File(outputFile).delete(); ldd2ldr.convert(path, outputFile); if (new File(outputFile).exists()) ldrawFile = LDrawFile .fileFromContentsAtPath(outputFile); } catch (Exception e) { e.printStackTrace(); } } else ldrawFile = LDrawFile.fileFromContentsAtPath(path); ldrawFileChanged(); System.out.println((System.nanoTime() - t) / 1000000000.0f + " seconds to load."); } }); if (BackgroundThreadManager.getInstance().isAllFinish() == false) new ProgressDlg(Display.getDefault().getActiveShell(), SWT.NONE) .open(); } public void importFile(String path, Vector3f pos) { LDrawFile file = LDrawFile.fileFromContentsAtPath(path); file.activeModel().setModelName(path); for (LDrawMPDModel model : file.submodels()) { ldrawFile.addSubmodel(model); } if (pos == null) { pos = new Vector3f(0, 0, 0); } String displayName = null; if (file.activeModel().modelName().contains("/")) displayName = file.activeModel().modelName() .substring(file.activeModel().modelName().lastIndexOf("/")); if (displayName == null && file.activeModel().modelName().contains("\\")) displayName = file .activeModel() .modelName() .substring( file.activeModel().modelName().lastIndexOf("\\") + 1); if (displayName == null) displayName = file.activeModel().modelName(); file.activeModel().setModelName(displayName); LDrawPart part = new LDrawPart(); part.initWithPartName(displayName, pos); part.setDisplayName(displayName); part.resolvePart(); addDirectiveToWorkingFile(part); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); } public void importLXFMLFile(String fileName) { DocumentBuilderFactory docBuildFact = DocumentBuilderFactory .newInstance(); Document docXML = null; try { DocumentBuilder docBuild = docBuildFact.newDocumentBuilder(); if (fileName.endsWith("lxf")) { ZipFile zip = new ZipFile(fileName); docXML = docBuild.parse(zip.getInputStream(zip .getEntry("IMAGE100.LXFML"))); zip.close(); } else { File file = new File(fileName); docXML = docBuild.parse(file); } } catch (Exception e) { e.printStackTrace(); } docXML.getDocumentElement().normalize(); ArrayList<Part> lddParts = new ArrayList<Part>(); NodeList brickList = docXML.getElementsByTagName("Brick"); NodeList partList; Element brickNode, partNode; ArrayList<String> parts = new ArrayList<String>(); String designID; Part part; for (int i = 0, j; i < brickList.getLength(); i++) { brickNode = (Element) brickList.item(i); designID = brickNode.getAttribute("designID"); partList = brickNode.getElementsByTagName("Part"); for (j = 0; j < partList.getLength(); j++) { partNode = (Element) partList.item(j); designID = ((Element) partNode).getAttribute("designID"); if (!parts.contains(designID)) { parts.add(designID); } part = new Part((Element) partNode); lddParts.add(part); } } } public void removeDirectiveFromWorkingFile(LDrawDirective directive) { removeDirectiveFromWorkingFile(directive, true); } public void removeDirectiveFromWorkingFile(LDrawDirective directive, boolean updateConnectivityManager) { if (directive instanceof LDrawStep) { LDrawStep step = (LDrawStep) directive; if (ldrawFile.activeModel().subdirectives().size() > 1) { ldrawFile.activeModel().removeDirective(step); currentStep = null; } for (LDrawDirective subDirectives : step.subdirectives()) { if (subDirectives instanceof LDrawPart) { globalConnectivityManager.removePart( (LDrawPart) subDirectives, updateConnectivityManager); brickSelectionManager.removePart((LDrawPart) subDirectives); } } BrickSelectionManager.getInstance().clearSelection( updateConnectivityManager); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged, new LDrawDirectiveRemoved(directive.enclosingDirective(), 0, directive)); } else if (directive instanceof LDrawPart) { LDrawStep parent = directive.enclosingStep(); LDrawPart part = (LDrawPart) directive; try { directive.enclosingStep().removeDirective(part); } catch (Exception e) { e.getStackTrace(); } BrickSelectionManager.getInstance().removePartFromSelection(part); globalConnectivityManager.removePart(part, updateConnectivityManager); brickSelectionManager.removePart(part); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartRemoved, new LDrawDirectiveRemoved(parent, 0, directive)); } updateGridRange(); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void removeSelectedDirective() { for (LDrawPart part : brickSelectionManager.getSelectedPartList()) { removeDirectiveFromWorkingFile(part); globalConnectivityManager.removePart(part); } brickSelectionManager.clearSelection(true); } public void rotateSelectedDirectiveBy(Vector3f degree) { if (brickSelectionManager.isEmpty()) return; LDrawPart centeredPart = brickMovementGuideRenderer.getLDrawPart(); if (centeredPart == null) centeredPart = brickSelectionManager.getFirstPart(); Matrix4 newTransform = getResultTransformMatrixOfRotateDirectiveByFromCenter( centeredPart, Math.abs(degree.length()), degree, centeredPart.position()); brickSelectionManager.getBrickGroupForTransform().applyTransform( centeredPart, newTransform); handleTransformChanged_SelectedDirective(); } public boolean saveAs(Shell shell, String filepath) { if (shell != null && filepath == null) { FileDialog fileDialog = new FileDialog(shell, SWT.SAVE); fileDialog.setFilterExtensions(new String[] { "*.ldr", "*.mpd", "*.dat" }); fileDialog.setFileName("untitled"); filepath = fileDialog.open(); } if (filepath == null) return false; File file = new File(filepath); if (shell != null && file.exists() == true) { MessageBox messageBox = new MessageBox(shell, SWT.ICON_QUESTION | SWT.YES | SWT.NO); messageBox .setMessage("Selected file is already exists. \r\n Do you want to overwrite it?"); if (messageBox.open() != SWT.YES) { return false; } } FileOutputStream fos; try { String str = ldrawFile.write(); fos = new FileOutputStream(file); fos.write(str.getBytes()); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); return false; } ldrawFile.setPath(filepath); isChanged = false; if (ldrawFile != null) if (ldrawFile.path() != null) Display.getCurrent().getActiveShell() .setText(APP_NAME + ": " + ldrawFile.path()); else Display.getCurrent().getActiveShell() .setText(APP_NAME + ": untitled"); return true; } public void saveFile() { removeEmptyStep(); if (ldrawFile.path() != null) saveAs(null, ldrawFile.path()); else saveAs(Display.getDefault().getActiveShell(), ldrawFile.path()); } public void setCurrentStep(LDrawStep step) { currentStep = step; } public void snapToGrid() { boolean useConnectivity = configurationManager.isUseConnectivity(); configurationManager.setUseConnectivity(false); ArrayList<LDrawPart> selectedPartList = brickSelectionManager .getSelectedPartList(); if (selectedPartList.size() == 0) return; LDrawPart lastSelectedPart = selectedPartList.get(selectedPartList .size() - 1); Vector3f pos = lastSelectedPart.position(); lastSelectedPart.setTransformationMatrix(Direction6T .getSnappedTransformMatrix(lastSelectedPart .transformationMatrix())); lastSelectedPart.moveBy(pos, configurationManager.getGridUnit()); brickSelectionManager.getBrickGroupForTransform().applyTransform( lastSelectedPart, lastSelectedPart.transformationMatrix()); brickSelectionManager.updateStartMoveTransformMatrixMap(); configurationManager.setUseConnectivity(useConnectivity); handleTransformChanged_SelectedDirective(); } public void updateGridRange() { float[] range = new float[6]; range[0] = 3.40282347E+38f; // minx range[1] = -3.40282347E+38f; // maxx range[2] = 3.40282347E+38f; // minz range[3] = -3.40282347E+38f; // maxz range[4] = 3.40282347E+38f; // bottom y range[5] = -3.40282347E+38f; // top y Matrix4 transform = new Matrix4(); transform.setIdentity(); ldrawFile.getRange(transform, range); range[4] = 3.40282347E+38f; // bottom y range[5] = -3.40282347E+38f; // top y metaInfoRenderer.setRange(range); } public void changeDirectiveIndex(LDrawStep step, LDrawDirective directive, int newIndex) { step.removeDirective(directive); step.insertDirective(directive, newIndex); if (directive instanceof LDrawPart) NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(step, directive)); } public void ChangeDirectivesParentStepAction(LDrawDirective directive, LDrawStep oldStep, LDrawStep newStep) { oldStep.removeDirective(directive); newStep.addDirective(directive); if (directive instanceof LDrawPart) { NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(oldStep, directive)); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(newStep, directive)); } } public void ChangeDirectivesParentStepAction(LDrawDirective directive, LDrawStep oldStep, LDrawStep newStep, int index) { oldStep.removeDirective(directive); newStep.insertDirective(directive, index); if (directive instanceof LDrawPart) { NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(oldStep, directive)); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartAdded, new LDrawDirectiveAdded(newStep, directive)); } } public ArrayList<LDrawPart> getAllPartInActiveModel() { return getAllPartInActiveModel(false); } public ArrayList<LDrawPart> getAllPartInActiveModel(boolean extractSubmodel) { LDrawModel model = ldrawFile.activeModel(); return LDrawUtilities.extractLDrawPartListModel(model, extractSubmodel); } public ArrayList<LDrawPart> getAllPartInFile() { ArrayList<LDrawPart> retList = new ArrayList<LDrawPart>(); if (ldrawFile == null) return retList; for (LDrawModel model : ldrawFile.submodels()) retList.addAll(LDrawUtilities.extractLDrawPartListModel(model, false)); return retList; } public Matrix4 getResultTransformMatrixOfRotateDirectiveByFromCenter( LDrawDirective directive, float angle, Vector3f rotationVector, Vector3f center) { if (LDrawPart.class.isInstance(directive)) { LDrawPart part = (LDrawPart) directive; if (MatrixMath.compareFloat(angle, 0) != 0) { return part.getTransformMatrixForRotateByDegrees(angle, rotationVector, center); } return part.transformationMatrix(); } return null; } public Matrix4 getResultTransformMatrixOfMoveDirectiveBy( LDrawDirective directive, Vector3f pos, boolean useSnap) { if (LDrawPart.class.isInstance(directive)) { LDrawPart part = (LDrawPart) directive; if (pos != null) return part.getTransformMatrixForMoveBy(pos, configurationManager.getGridUnit(), useSnap); return part.transformationMatrix(); } return null; } public void setChanged() { isChanged = true; } public boolean checkChanged(Shell shell) { if (isChanged) { MessageBox box = new MessageBox(shell, SWT.YES | SWT.NO | SWT.CANCEL | SWT.APPLICATION_MODAL | SWT.ICON_QUESTION); box.setText("Your changes will be lost if you don't save"); box.setMessage("Do you want to save the changes you made to Model?"); switch (box.open()) { case SWT.YES: return saveAs(shell, ldrawFile.path()); case SWT.NO: return true; case SWT.CANCEL: return false; } } return true; } public void autoGrouping() { ArrayList<LDrawPart> initialLists = brickSelectionManager .getSelectedPartList(); if (initialLists.size() == 0) { return; } ArrayList<LDrawPart> groupedLists = new ArrayList<LDrawPart>( initialLists.size()); autoGrouping(initialLists, groupedLists); } private void autoGrouping(ArrayList<LDrawPart> initialLists, ArrayList<LDrawPart> groupedLists) { ArrayList<LDrawPart> connectedParts; LDrawStep oldStep, newStep; for (LDrawPart part : initialLists) { if (groupedLists.contains(part)) continue; newStep = ldrawFile.activeModel().addStep(); connectedParts = GlobalConnectivityManager.getInstance() .getConnectedPart(part, null, null, true); for (LDrawPart connectedPart : connectedParts) { oldStep = connectedPart.enclosingStep(); if (oldStep == null) continue; removeDirectiveFromWorkingFile(connectedPart); if (oldStep.size() == 0) { removeDirectiveFromWorkingFile(oldStep); } addDirectiveToWorkingFile(newStep, connectedPart); groupedLists.add(connectedPart); } } } public void removeEmptyStep() { ArrayList<LDrawStep> emptyStepList = new ArrayList<LDrawStep>(); for (LDrawStep step : ldrawFile.activeModel().steps()) { boolean isContainPart = false; for (LDrawDirective directive : step.subdirectives()) if (directive instanceof LDrawPart) { isContainPart = true; break; } if (isContainPart == false) emptyStepList.add(step); } for (LDrawStep step : emptyStepList) removeDirectiveFromWorkingFile(step, false); } public void hideAllStep() { for (LDrawStep step : getWorkingLDrawFile().activeModel().steps()) { for (LDrawDirective directive : step.subdirectives()) if (directive instanceof LDrawPart) ((LDrawPart) directive).setHidden(true); } } public void showStep(int index) { LDrawStep step = getWorkingLDrawFile().activeModel().steps().get(index); if (step == null) return; for (LDrawDirective directive : step.subdirectives()) if (directive instanceof LDrawPart) ((LDrawPart) directive).setHidden(false); } public int getNumOfSteps() { return getWorkingLDrawFile().activeModel().steps().size(); } public void showAllStep() { for (LDrawStep step : getWorkingLDrawFile().activeModel().steps()) { for (LDrawDirective directive : step.subdirectives()) if (directive instanceof LDrawPart) ((LDrawPart) directive).setHidden(false); } NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void hideStep(int index) { LDrawStep step = getWorkingLDrawFile().activeModel().steps().get(index); if (step == null) return; for (LDrawDirective directive : step.subdirectives()) if (directive instanceof LDrawPart) ((LDrawPart) directive).setHidden(true); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void adjustRotationMatrixForSelectedDirective() { if (brickSelectionManager.isEmpty()) return; ArrayList<LDrawPart> selectedPartList = brickSelectionManager .getSelectedPartList(); Matrix4 rotationMatrix = selectedPartList.get( selectedPartList.size() - 1).transformationMatrix(); rotationMatrix.element[3][0] = rotationMatrix.element[3][1] = rotationMatrix.element[3][2] = 0; for (LDrawPart part : selectedPartList) { Matrix4 partTransform = part.transformationMatrix(); Matrix4 newTransform = new Matrix4(rotationMatrix); for (int i = 0; i < 3; i++) newTransform.element[3][i] = partTransform.element[3][i]; part.setTransformationMatrix(newTransform); } handleTransformChanged_SelectedDirective(); } public void alignSelectedDirective(Direction6T direction) { ArrayList<LDrawPart> selectedPartList = brickSelectionManager .getSelectedPartList(); if (selectedPartList.size() < 2) return; LDrawPart basis = null; for (LDrawPart part : selectedPartList) { if (basis == null) { basis = part; continue; } Box3 boundingBox = part.boundingBox3(); Vector3f min = boundingBox.getMax(); Vector3f max = boundingBox.getMin(); boolean flag = false; switch (direction) { case X_Minus: if (min.x < basis.boundingBox3().getMin().x) flag = true; break; case X_Plus: if (max.x > basis.boundingBox3().getMax().x) flag = true; break; case Y_Minus: if (min.y < basis.boundingBox3().getMin().y) flag = true; break; case Y_Plus: if (max.y > basis.boundingBox3().getMax().y) flag = true; break; case Z_Minus: if (min.z < basis.boundingBox3().getMin().z) flag = true; break; case Z_Plus: if (max.z > basis.boundingBox3().getMax().z) flag = true; break; } if (flag == true) { basis = part; } } Box3 boundingBox_basis = basis.boundingBox3(); for (LDrawPart part : selectedPartList) { if (part == basis) continue; Box3 boundingBox = part.boundingBox3(); Vector3f min = boundingBox.getMin(); Vector3f max = boundingBox.getMax(); Matrix4 newTransform = part.transformationMatrix(); switch (direction) { case X_Minus: newTransform.translate(boundingBox_basis.getMin().x - min.x, 0, 0); break; case X_Plus: newTransform.translate(boundingBox_basis.getMax().x - max.x, 0, 0); break; case Y_Minus: newTransform.translate(0, boundingBox_basis.getMin().y - min.y, 0); break; case Y_Plus: newTransform.translate(0, boundingBox_basis.getMax().y - max.y, 0); break; case Z_Minus: newTransform.translate(0, 0, boundingBox_basis.getMin().z - min.z); break; case Z_Plus: newTransform.translate(0, 0, boundingBox_basis.getMax().z - max.z); break; } part.setTransformationMatrix(newTransform); } handleTransformChanged_SelectedDirective(); } public void handleTransformChanged_SelectedDirective() { MovePartsAction action = new MovePartsAction(); Matrix4 originalMatrix; ArrayList<LDrawPart> partList = brickSelectionManager .getSelectedPartList(); for (LDrawPart part : partList) { brickSelectionManager.updateScreenProjectionVerticesMap(part); originalMatrix = BrickSelectionManager.getInstance() .getInitialMoveTransformMatrix(part); if (originalMatrix == null) continue; action.addMovePart(part, originalMatrix, part.transformationMatrix()); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawPartTransformed, new LDrawDirectiveModified(part)); } LDrawUndoRedoManager.getInstance().pushUndoAction(action); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void makeNewStepFromSeletion() { LDrawStep newStep = addStepToWorkingFile(); LDrawStep parentStep; DirectiveAction action = new DirectiveAction(); ArrayList<LDrawPart> selectedPartList = brickSelectionManager .getSelectedPartList(); for (LDrawPart part : getAllPartInActiveModel()) { if (selectedPartList.contains(part)) { action.removeDirective(part); parentStep = part.enclosingStep(); parentStep.removeDirective(part); if (parentStep.size() == 0) { mocBuilder.removeDirectiveFromWorkingFile(parentStep); } newStep.addDirective(part); } } action.addDirective(newStep); LDrawUndoRedoManager.getInstance().pushUndoAction(action); } public void setAuthor(String author) { if (this.ldrawFile != null && this.ldrawFile.activeModel() != null) { this.ldrawFile.activeModel().setAuthor(author); } } public String getAuthor() { if (this.ldrawFile != null && this.ldrawFile.activeModel() != null) return this.ldrawFile.activeModel().author(); return ""; } public void setModelName(String name) { if (this.ldrawFile != null && this.ldrawFile.activeModel() != null) { this.ldrawFile.activeModel().setFileName(name); } } public String getModelName() { if (this.ldrawFile != null && this.ldrawFile.activeModel() != null) return this.ldrawFile.activeModel().fileName(); return ""; } public void changeActiveModel(LDrawMPDModel model) { if (model == null) return; ldrawFile.setActiveModel(model); ldrawFileChanged(); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public LDrawMPDModel getActiveModel() { if (ldrawFile == null) return null; return ldrawFile.activeModel(); } public void renameModel(LDrawMPDModel model, String newName) { if (ldrawFile == null) return; ldrawFile.renameModel(model, newName); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); } public void removeModel(LDrawMPDModel model) { if (ldrawFile == null) return; ldrawFile.removeDirective(model); ldrawFileChanged(); } public LDrawMPDModel makeASubmodel() { if (ldrawFile == null) return null; LDrawMPDModel newModel = LDrawMPDModel.model(); int counter = 0; while (ldrawFile.modelNames().contains(newModel.modelName())) { newModel.setModelName("UntitledModel_" + counter); counter++; } newModel.addStep(); ldrawFile.addSubmodel(newModel); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); return newModel; } public void makeASubmodelFromSelection() { if (ldrawFile == null) return; if(brickSelectionManager.isEmpty())return; LDrawMPDModel newModel = LDrawMPDModel.model(); int counter = 0; while (ldrawFile.modelNames().contains(newModel.modelName())) { newModel.setModelName("UntitledModel_" + counter); counter++; } LDrawStep newStep = new LDrawStep(); ArrayList<LDrawPart> selectedPartList = brickSelectionManager .getSelectedPartList(); Vector3f centerPos = brickSelectionManager.getPartHavingMinY() .boundingBox3().getMax(); removeSelectedDirective(); for (LDrawPart part : selectedPartList) { part.moveTo(part.position().sub(centerPos), LDrawGridTypeT.Fine); newStep.addDirective(part); } newModel.addStep(newStep); ldrawFile.addSubmodel(newModel); LDrawPart part = new LDrawPart(); part.initWithPartName(newModel.modelName(), centerPos); part.setDisplayName(newModel.modelName()); addDirectiveToWorkingFile(part); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void extractPartsFromASubmodel(LDrawPart part) { if (ldrawFile == null) return; if (part == null) return; if (part.getCacheType() != PartTypeT.PartTypeSubmodel) return; if (part.getCacheModel() == null) return; Matrix4 partTransform = part.transformationMatrix(); for (LDrawDirective directive_Step : part.getCacheModel() .subdirectives()) { try { LDrawDirective clone_Step = (LDrawDirective) (directive_Step .clone()); if (clone_Step instanceof LDrawStep) { for (LDrawDirective directive_part : ((LDrawStep) clone_Step) .subdirectives()) { if (directive_part instanceof LDrawPart) { LDrawPart tempPart = (LDrawPart) directive_part; Matrix4 newTransform = tempPart .transformationMatrix(); newTransform.multiply(partTransform); tempPart.setTransformationMatrix(newTransform); } } } addDirectiveToWorkingFile(clone_Step); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } removeDirectiveFromWorkingFile(part); NotificationCenter.getInstance().postNotification( NotificationMessageT.LDrawFileActiveModelDidChanged); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } public void hideSelectedParts() { for (LDrawPart part : brickSelectionManager .getSelectedPartList()) part.setHidden(true); brickSelectionManager.clearSelection(); NotificationCenter.getInstance().postNotification( NotificationMessageT.NeedReDraw); } }